/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package DAO;

import DAO.exceptions.IllegalOrphanException;
import DAO.exceptions.NonexistentEntityException;
import DAO.exceptions.PreexistingEntityException;
import dominio.Cliente;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import dominio.Telefone;
import dominio.Consorcio;
import dominio.Endereco;
import java.util.ArrayList;

/**
 *
 * @author gilcemar e naliane
 */
public class ClienteJpaController {

    public ClienteJpaController() {
        emf = Persistence.createEntityManagerFactory("ProjetoTraxxPU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Cliente cliente) throws PreexistingEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Telefone telefone = cliente.getTelefone();
            if (telefone != null) {
                telefone = em.getReference(telefone.getClass(), telefone.getCpf());
                cliente.setTelefone(telefone);
            }
            Consorcio consorcio = cliente.getConsorcio();
            if (consorcio != null) {
                consorcio = em.getReference(consorcio.getClass(), consorcio.getCpf());
                cliente.setConsorcio(consorcio);
            }
            Endereco endereco = cliente.getEndereco();
            if (endereco != null) {
                endereco = em.getReference(endereco.getClass(), endereco.getCpf());
                cliente.setEndereco(endereco);
            }
            em.persist(cliente);
            if (telefone != null) {
                Cliente oldClienteOfTelefone = telefone.getCliente();
                if (oldClienteOfTelefone != null) {
                    oldClienteOfTelefone.setTelefone(null);
                    oldClienteOfTelefone = em.merge(oldClienteOfTelefone);
                }
                telefone.setCliente(cliente);
                telefone = em.merge(telefone);
            }
            if (consorcio != null) {
                Cliente oldClienteOfConsorcio = consorcio.getCliente();
                if (oldClienteOfConsorcio != null) {
                    oldClienteOfConsorcio.setConsorcio(null);
                    oldClienteOfConsorcio = em.merge(oldClienteOfConsorcio);
                }
                consorcio.setCliente(cliente);
                consorcio = em.merge(consorcio);
            }
            if (endereco != null) {
                Cliente oldClienteOfEndereco = endereco.getCliente();
                if (oldClienteOfEndereco != null) {
                    oldClienteOfEndereco.setEndereco(null);
                    oldClienteOfEndereco = em.merge(oldClienteOfEndereco);
                }
                endereco.setCliente(cliente);
                endereco = em.merge(endereco);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            if (findCliente(cliente.getCpf()) != null) {
                throw new PreexistingEntityException("Cliente " + cliente + " already exists.", ex);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Cliente cliente) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Cliente persistentCliente = em.find(Cliente.class, cliente.getCpf());
            Telefone telefoneOld = persistentCliente.getTelefone();
            Telefone telefoneNew = cliente.getTelefone();
            Consorcio consorcioOld = persistentCliente.getConsorcio();
            Consorcio consorcioNew = cliente.getConsorcio();
            Endereco enderecoOld = persistentCliente.getEndereco();
            Endereco enderecoNew = cliente.getEndereco();
            List<String> illegalOrphanMessages = null;
            if (consorcioOld != null && !consorcioOld.equals(consorcioNew)) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("You must retain Consorcio " + consorcioOld + " since its cliente field is not nullable.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (telefoneNew != null) {
                telefoneNew = em.getReference(telefoneNew.getClass(), telefoneNew.getCpf());
                cliente.setTelefone(telefoneNew);
            }
            if (consorcioNew != null) {
                consorcioNew = em.getReference(consorcioNew.getClass(), consorcioNew.getCpf());
                cliente.setConsorcio(consorcioNew);
            }
            if (enderecoNew != null) {
                enderecoNew = em.getReference(enderecoNew.getClass(), enderecoNew.getCpf());
                cliente.setEndereco(enderecoNew);
            }
            cliente = em.merge(cliente);
            if (telefoneNew != null && !telefoneNew.equals(telefoneOld)) {
                Cliente oldClienteOfTelefone = telefoneNew.getCliente();
                if (oldClienteOfTelefone != null) {
                    oldClienteOfTelefone.setTelefone(null);
                    oldClienteOfTelefone = em.merge(oldClienteOfTelefone);
                }
                telefoneNew.setCliente(cliente);
                telefoneNew = em.merge(telefoneNew);
            }
            if (consorcioNew != null && !consorcioNew.equals(consorcioOld)) {
                Cliente oldClienteOfConsorcio = consorcioNew.getCliente();
                if (oldClienteOfConsorcio != null) {
                    oldClienteOfConsorcio.setConsorcio(null);
                    oldClienteOfConsorcio = em.merge(oldClienteOfConsorcio);
                }
                consorcioNew.setCliente(cliente);
                consorcioNew = em.merge(consorcioNew);
            }
            if (enderecoNew != null && !enderecoNew.equals(enderecoOld)) {
                Cliente oldClienteOfEndereco = enderecoNew.getCliente();
                if (oldClienteOfEndereco != null) {
                    oldClienteOfEndereco.setEndereco(null);
                    oldClienteOfEndereco = em.merge(oldClienteOfEndereco);
                }
                enderecoNew.setCliente(cliente);
                enderecoNew = em.merge(enderecoNew);
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                String id = cliente.getCpf();
                if (findCliente(id) == null) {
                    throw new NonexistentEntityException("The cliente with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(String id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Cliente cliente;
            try {
                cliente = em.getReference(Cliente.class, id);
                cliente.getCpf();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The cliente with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            Consorcio consorcioOrphanCheck = cliente.getConsorcio();
            if (consorcioOrphanCheck != null) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Cliente (" + cliente + ") cannot be destroyed since the Consorcio " + consorcioOrphanCheck + " in its consorcio field has a non-nullable cliente field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            em.remove(cliente);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Cliente> findClienteEntities() {
        return findClienteEntities(true, -1, -1);
    }

    public List<Cliente> findClienteEntities(int maxResults, int firstResult) {
        return findClienteEntities(false, maxResults, firstResult);
    }

    private List<Cliente> findClienteEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Cliente.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Cliente findCliente(String id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Cliente.class, id);
        } finally {
            em.close();
        }
    }

    public List<Cliente> findForName (String nome) {
        EntityManager em = getEntityManager();
        try {
            List<Cliente> resultado = new ArrayList<Cliente>();
            Query clientes= em.createNamedQuery("Cliente.findByNome").setParameter("nome", nome);
            resultado = clientes.getResultList();
            return resultado;
        } finally {
            em.close();
        }
    }

    public int getClienteCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Cliente> rt = cq.from(Cliente.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
